package com.xingtu.testSerialport.utils;

import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ObjectUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * Author:雅典娜
 * Created on 2024/4/2
 * 别总是抱怨生活不够幸运，是你欠了生活一份努力，
 * 每一个你讨厌的现在，都有一个不够努力的曾经，
 * 未来美不美，取决于你现在拼不拼。
 * Desc:
 * 后台:
 */
public class SerialPortUtils {


    public static boolean CRCCheck(String input) {
//        LogUtils.e("CRCCheck-> " + input);
        //$GPGGA,091929.00,4544.45203793,N,12641.28213220,E,5,09,4.5,-163.1561,M,14.2213,M,07,0004*42
        String[] strArr = input.split("\\*");
        if (strArr == null || strArr.length < 2)
            return false;

        String str = strArr[0];
        char ch = str.charAt(1);
        int x = (int) ch;
        int y;
        for (int i = 2; i < str.length(); i++) {
            y = (int) str.charAt(i);
            x = x ^ y;
        }
        //转换成十六进制形式
        String check = Integer.toHexString(x);
        if (check.equals(strArr[1]))
            return true;

        return false;
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
                    16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    // 转化十六进制编码为字符串
    public static String toStringHex2(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
                        i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "utf-8");// UTF-16le:Not
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    //<editor-fold desc="按照指定数量分割数组">

    /**
     * 按指定大小，分隔集合，将集合按规定个数分为n个部分
     *
     * @param list
     * @param len
     * @return
     */
    public static List<List<?>> splitList(List<?> list, int len) {
        if (list == null || list.size() == 0 || len < 1) {
            return null;
        }
        List<List<?>> result = new ArrayList<List<?>>();
        int size = list.size();
        int count = (size + len - 1) / len;
        for (int i = 0; i < count; i++) {
            List<?> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }
    //</editor-fold>

    public static List<String> splitString(String str, int len) {
        List<String> result = new ArrayList<>();
        int start = 0;
        while (start < str.length()) {
            int end = Math.min(start + len, str.length());
            String subStr = str.substring(start, end);
            result.add(subStr);
            start += len;
        }
        return result;
    }

    public static String sortNewHex2(String hex) {
        if (ObjectUtils.isEmpty(hex)) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        List<String> newList = splitString(hex, 2);
        for (int i = newList.size() - 1; i >= 0; i--) {
            stringBuilder.append(newList.get(i));
        }
//        LogUtils.e("重新排序的十六进制：" + stringBuilder.toString());

        return stringBuilder.toString();
    }


    //<editor-fold desc="16进制转十进制 正负数">
    public static int getHexB10Int(String hex) {
        BigInteger bi = new BigInteger(hex, 16);
        int a = bi.intValue();
        return a;
    }
    //</editor-fold>

    //<editor-fold desc="16进制转十进制 正负数">
    public static int getNewHexToInt(String hex) {
        BigInteger bi = new BigInteger(hex, 16);
        int a = bi.intValue();
        return a;
    }
    //</editor-fold>

    //<editor-fold desc="角度 保留精度0.0001">
    public static String getAngleStr(String hex, boolean isNeedToSort) {
        if (isNeedToSort) {
            hex = SerialPortUtils.sortNewHex2(hex);
        }
        double a = SerialPortUtils.getNewHexToInt(hex) * 0.0001;
        return getBigDecimal(String.valueOf(a), 4);
    }
    //</editor-fold>


    public static String getNewHexToFloat(String hex) {
        String r = BinaryStringToFloat(HexString2binaryString(hex));
        return r;
    }


    // 16进制字符串转化二进制字符串
    public static String HexString2binaryString(String hexString) {
        if (hexString == null || hexString.length() % 2 != 0)
            return null;
        String bString = "", tmp;
        for (int i = 0; i < hexString.length(); i++) {
            tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
            bString += tmp.substring(tmp.length() - 4);
        }
        return bString;
    }

    // 2进制字符串转Float数，包括正数和负数
    static String BinaryStringToFloat(final String binaryString) {
        // float是32位，将这个binaryString左边补0补足32位，如果是Double补足64位。
        /* final String stringValue = LeftPad(binaryString, '0', 32); */
        // 首位是符号部分，占1位。
        // 如果符号位是0则代表正数，1代表负数
        final int sign = binaryString.charAt(0) == '0' ? 1 : -1;
        // 第2到9位是指数部分，float占8位，double占11位。
        final String exponentStr = binaryString.substring(1, 9);
        // 将这个二进制字符串转成整数，由于指数部分加了偏移量（float偏移量是127，double是1023）
        // 所以实际值要减去127
        final int exponent = Integer.parseInt(exponentStr, 2) - 127;
        // 最后的23位是尾数部分，由于规格化数，小数点左边隐含一个1，现在加上
        final String mantissaStr = "1".concat(binaryString.substring(9, 32));
        // 这里用double，尽量保持精度，最好用BigDecimal，这里只是方便计算所以用double
        double mantissa = 0.0;

        for (int i = 0; i < mantissaStr.length(); i++) {
            final int intValue = Character.getNumericValue(mantissaStr.charAt(i));
            // 计算小数部分，具体请查阅二进制小数转10进制数相关资料
            mantissa += (intValue * Math.pow(2, -i));
        }
        // 根据IEEE 754 标准计算：符号位 * 2的指数次方 * 尾数部分
        double d = (sign * Math.pow(2, exponent) * mantissa);
        BigDecimal price = new BigDecimal(d).setScale(4, BigDecimal.ROUND_HALF_UP);
        return price.toString();
    }


    /**
     * 注释：拼接byte[]
     *
     * @param args 可变参数，byte数组
     * @return
     */
    public static byte[] byteAppand(byte[]... args) {
        byte[] bb = new byte[0];
        for (int i = 0; i < args.length; i++) {
            byte[] bbb = args[i];
            if (bbb == null || bbb.length == 0) continue;
            byte[] bbbb = new byte[bb.length + bbb.length];
            System.arraycopy(bb, 0, bbbb, 0, bb.length);
            System.arraycopy(bbb, 0, bbbb, bb.length, bbb.length);
            bb = bbbb;
        }
        return bb;
    }

    /**
     * 注释：int到字节数组的转换！
     *
     * @param number
     * @return
     */
    public static byte[] intToByte(int number) {
        int temp = number;
        byte[] b = new byte[2];
        for (int i = 0; i < b.length; i++) {
            b[i] = Integer.valueOf(temp & 0xff).byteValue();// 将最低位保存在最低位
            temp = temp >> 8; // 向右移8位
        }
        return b;
    }

    //    //高位在前，低位在后
    public static byte[] int2bytes4(int num) {
        LogUtils.e("num=" + num);
        byte[] result = new byte[4];
        result[0] = (byte) ((num >>> 24) & 0xff);//说明一
        result[1] = (byte) ((num >>> 16) & 0xff);
        result[2] = (byte) ((num >>> 8) & 0xff);
        result[3] = (byte) ((num >>> 0) & 0xff);
        return result;
    }

    //    //高位在前，低位在后
    public static byte[] int2bytes2(int num) {
        byte[] result = new byte[2];
        result[0] = (byte) ((num >>> 8) & 0xff);
        result[1] = (byte) ((num >>> 0) & 0xff);
        return result;
    }

    //    //高位在前，低位在后
    public static byte[] int2bytes1(int num) {
        byte[] result = new byte[1];
        result[0] = (byte) ((num >>> 0) & 0xff);
//        LogUtils.e("int2bytes1 = "+result[0]);
        return result;
    }

    //<editor-fold desc="发送串口信息">
    //版本信息
    public final static int code1 = 0x11; //杆臂配置信息
    public final static int code2 = 0x12;//IMU信息输出
    public final static int code3 = 0x13;//IMU配置安装旋转角
    public final static int rCode1 = 0x01;//返回IMU信息
    public final static int rCode2 = 0x02;//杆臂配置信息应答
    public final static int rCode3 = 0x03;//信息输出应答

    /**
     * 拼接发送报文
     *
     * @param ResponseNumber
     * @param SendMsg
     * @return
     */
    public static byte[] GetMsgBytes(int ResponseNumber,
                                     byte[] SendMsg) {
        // 帧头
        byte[] b = new byte[3];
        b[0] = (byte) 0xFF;
        b[1] = (byte) 0x4A;
        b[2] = (byte) 0xA4;
        // 长度 帧头3BYTE+长度1BYTE+功能码1BYTE+数据字节数nBYTE+校验1BYTE
        byte[] lenghByte = new byte[1];
        lenghByte[0] = (byte) (3 + 1 + 1 + SendMsg.length + 1);
        //拼接
        b = byteAppand(b, lenghByte);
        // 功能码 1BYTE 01版本信息  0x0A写ID报文  0x03控制报文 0x04升级报文
        byte[] funcByte = new byte[1];
        funcByte[0] = (byte) (ResponseNumber);
        //拼接 功能码byte
        b = byteAppand(b, funcByte);
        // 数据 nBYTE 拼接
        b = byteAppand(b, SendMsg);

        // 校验和,保留低8位
        byte[] checkSumByte = new byte[1];
        int checkSumNum = 0;
        for (int i = 0; i < b.length; i++) {
            checkSumNum += b[i];
        }
        checkSumByte[0] = Integer.valueOf(checkSumNum & 0xff).byteValue();// 将最低位保存在最低位
        // 拼接校验和
        b = byteAppand(b, checkSumByte);
        LogUtils.e("sendLength=" + SendMsg.length, "长度=" + lenghByte[0]);
        return b;
    }
    //</editor-fold>

    public static void calculateBytesize(long number) {
        if (number >= Byte.MIN_VALUE && number <= Byte.MAX_VALUE) {
            LogUtils.e(number + "->该数字占据1个字节。");
        } else if (number >= Short.MIN_VALUE && number <= Short.MAX_VALUE) {
            LogUtils.e(number + "->该数字占据2个字节。");
        } else if (number >= Integer.MIN_VALUE && number <= Integer.MAX_VALUE) {
            LogUtils.e(number + "->该数字占据4个字节。");
        } else {
            LogUtils.e(number + "->该数字占据8个字节。");
        }
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static String parseHexStr2Byte1(String hexStr) {
        if (hexStr.length() == 0)
            return null;
        int sint = Integer.valueOf(hexStr, 16);
        //十进制在转换成二进制的字符串形式输出!
        String bin = Integer.toBinaryString(sint);
        for (int i = bin.length(); i < 4; i++) {
            bin = "0" + bin;
        }
        return bin;
    }


    //十进制转16进制
    public static String intToHex(int n) {
        StringBuffer s = new StringBuffer();
        String a;
        char[] b = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        while (n != 0) {
            s = s.append(b[n % 16]);
            n = n / 16;
        }
        a = s.reverse().toString();
        return a;
    }

    public static String getBigDecimal(String text, int scale) {
        if (ObjectUtils.isEmpty(text)) {
            return "0";
        }
        BigDecimal price = new BigDecimal(text).setScale(scale, BigDecimal.ROUND_HALF_UP);
        text = price.toString();
//        LogUtils.d("库存格式化后数据：" + text);
        return text;
    }

}
